// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2025-02-25

package providers

import (
	"fmt"
	"gitee.com/go-libs/console"
	"os"
	"regexp"
	"strings"
)

var (
	regexYamlHasMultiple = regexp.MustCompile("\n-{3}")
	regexYamlSeparator   = regexp.MustCompile(`^-{3}`)
)

type Executor struct {
}

// Save
// 保存文件.
func (o *Executor) Save(container *console.Container, target *Target, override bool) (err error) {
	var (
		file     *os.File
		filename = fmt.Sprintf(`%s/%s`, target.Path, target.Name)
		ignored  bool
		info     os.FileInfo
		size     int
	)

	// 1. 监听结束.
	defer func() {
		if r := recover(); r != nil {
			// 1.1 捕获异常.
			container.GetOutput().Fatal(`  - {%s}: %v`, filename, r)

			if err == nil {
				err = fmt.Errorf(`%v`, r)
			}
		} else {
			// 1.2 记录结果.
			if err != nil {
				container.GetOutput().Error(`  - {%s}: %v`, filename, err)
			} else {
				if ignored {
					container.GetOutput().Info(`  - {%s}: size=%d, ignored`, filename, size)
				} else {
					container.GetOutput().Info(`  - {%s}: size=%d, created`, filename, size)
				}
			}
		}

		// 1.3 关闭文件.
		if file != nil {
			_ = file.Close()
		}
	}()

	// 2. 校验目录.
	if info, err = os.Stat(target.Path); err != nil {
		// 2.1 权限检测.
		if !os.IsNotExist(err) {
			return
		}

		// 2.2 创建目录.
		if err = os.MkdirAll(target.Path, os.ModePerm); err != nil {
			return
		}
	} else if info != nil && !info.IsDir() {
		// 2.3 无效目录.
		err = fmt.Errorf(`invalid directory: %s`, target.Path)
		return
	}

	// 3. 忽略文件.
	//    若指定文件已经存在且未设置覆盖, 则跳过.
	if !override {
		if info, err = os.Stat(filename); err != nil {
			// 3.1 权限错误.
			if !os.IsNotExist(err) {
				return
			}
		} else if info.IsDir() {
			// 3.2 无效文件.
			err = fmt.Errorf(`invalid file: %s`, filename)
			return
		} else {
			// 3.3 忽略文件.
			//     若目标文件已经存在则跳过.
			ignored = true
			return
		}
	}

	// 4. 打开文件.
	if file, err = os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.ModePerm); err != nil {
		return
	}

	// 5. 写入内容.
	size, err = file.WriteString(target.Text)
	return
}

// YamlHasSeparator
// YAML格式配置配置有分隔符.
func (o *Executor) YamlHasSeparator(text string) bool {
	return regexYamlHasMultiple.MatchString("\n" + text)
}

// YamlSplit
// 分隔带分隔符的YAML配置内容为多个文件.
func (o *Executor) YamlSplit(text string) [][]string {
	var (
		list  []string
		lists = make([][]string, 0)
		start = false
	)

	for _, s := range strings.Split(text, "\n") {
		if regexYamlSeparator.MatchString(s) {
			if list != nil {
				lists = append(lists, list)
			}

			start = true
			continue
		}

		if start {
			if list == nil {
				list = make([]string, 0)
			}

			list = append(list, s)
		}
	}

	return lists
}
